package com.slz3.business.module.goodsManagement.baseGoods.service;

import com.slz3.business.frame.enums.ValidFlag;
import com.slz3.business.frame.module.Repositorys;
import com.slz3.business.frame.module.Services;
import com.slz3.business.frame.util.UUIDUtils;
import com.slz3.business.module.goodsManagement.baseGoods.domain.BaseGoods;
import com.slz3.business.module.goodsManagement.baseGoods.domain.BaseGoodsFactory;
import com.slz3.business.module.goodsManagement.gooBaseGoodsAttribute.domain.GooBaseGoodsAttribute;
import com.slz3.business.module.goodsManagement.gooBaseGoodsAttributeValue.domain.GooBaseGoodsAttributeValue;
import com.slz3.business.module.goodsManagement.gooBaseGoodsSpecification.domain.GooBaseGoodsSpecification;
import com.slz3.business.module.goodsManagement.gooBaseGoodsSpecificationValue.domain.GooBaseGoodsSpecificationValue;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

@Slf4j
@Service
public class BaseGoodsTransactionalServiceImpl implements BaseGoodsTransactionalService {

    @Override
    public BaseGoods modify(BaseGoods baseGoodsNew) {
        //delete data
        List<GooBaseGoodsAttribute> attributes = baseGoodsNew.getGooBaseGoodsAttributeList();
        BaseGoods baseGoods = Repositorys.baseGoods.saveAndFlush(BaseGoodsFactory.initBaseFields(baseGoodsNew));
        UUID uuid = baseGoods.getUuid();

        List<GooBaseGoodsAttribute> attributesDb = Repositorys.gooBaseGoodsAttribute.findAllByFkBaseGoodsUUID(uuid);
        attributesDb.forEach(item -> {
            List<GooBaseGoodsAttributeValue> attributeValues = Repositorys.gooBaseGoodsAttributeValue.findAllByUpper(item.getUuid());
            Repositorys.gooBaseGoodsAttributeValue.deleteInBatch(attributeValues);
        });
        Repositorys.gooBaseGoodsAttribute.deleteInBatch(attributesDb);

        //add data
        List<GooBaseGoodsAttribute> saveAttributes = getGooBaseGoodsAttributes(attributes, uuid);
        baseGoods.setGooBaseGoodsAttributeList(saveAttributes);

        //修改规格
        //前端传递的规格
        List<GooBaseGoodsSpecification> specifications = baseGoodsNew.getSpecifications();
        //从数据库中查询
        GooBaseGoodsSpecification specification = new GooBaseGoodsSpecification();
        specification.setValidFlag(ValidFlag.VALID);
        specification.setFkGooBaseGoodsUuid(uuid);
        List<GooBaseGoodsSpecification> goodsSpecificationAll = Repositorys.gooBaseGoodsSpecification.findAll(Example.of(specification));

        //数据库查询的规格有,前端传递的规格没有,删除 ,根据名称判断
        List<GooBaseGoodsSpecification> distinct = getDistinct(goodsSpecificationAll, specifications);

        //删除中间表,逻辑删除
        deleteSpecs(distinct);


        //前端传递的规格有,数据库查询的规格没有,添加
        List<GooBaseGoodsSpecification> distinct2 = getDistinct(specifications, goodsSpecificationAll);
        if(!distinct2.isEmpty()){
            List<GooBaseGoodsSpecificationValue> values = new ArrayList<>();
            distinct2.forEach(item -> {
                item.setFkGooBaseGoodsUuid(uuid);
                item.setUuid(UUIDUtils.generateUUID());
                List<GooBaseGoodsSpecificationValue> specificationValues = item.getGoodsSpecificationValues();
                GooBaseGoodsSpecification save = Repositorys.gooBaseGoodsSpecification.save(item);
                specificationValues.forEach(value -> {
                    value.setUuid(UUIDUtils.generateUUID());
                    value.setUpper(save.getUuid());
                });
                values.addAll(specificationValues);
            });
            //保存规格,属性值中间表
            Repositorys.gooBaseGoodsSpecificationValue.saveAll(values);
        }
        return baseGoods;
    }

    private List<GooBaseGoodsAttribute> getGooBaseGoodsAttributes(List<GooBaseGoodsAttribute> attributes, UUID uuid) {
        List<GooBaseGoodsAttribute> saveAttributes = new ArrayList<>();
        attributes.forEach(item -> {
            List<GooBaseGoodsAttributeValue> attributeValues = item.getGooBaseGoodsAttributeValueList();
            item.setFkBaseGoodsUUID(uuid);
            item.setUuid(UUIDUtils.generateUUID());
            GooBaseGoodsAttribute attribute = Repositorys.gooBaseGoodsAttribute.save(item);
            attributeValues.forEach(value -> {
                value.setUpper(attribute.getUuid());
                value.setUuid(UUIDUtils.generateUUID());
            });
            List<GooBaseGoodsAttributeValue> values = Repositorys.gooBaseGoodsAttributeValue.saveAll(attributeValues);
            attribute.setGooBaseGoodsAttributeValueList(values);
            saveAttributes.add(attribute);
        });
        return saveAttributes;
    }

    private List<GooBaseGoodsSpecification> getDistinct(List<GooBaseGoodsSpecification> first, List<GooBaseGoodsSpecification> second) {
        return first.stream().filter(item -> {
            boolean result = true;
            for (GooBaseGoodsSpecification spec : second) {
                if (spec.getSerName().equals(item.getSerName())) {
                    result = false;
                    break;
                }
            }
            return result;
        }).collect(Collectors.toList());
    }


    @Override
    public BaseGoods save(BaseGoods baseGoods) {
        List<GooBaseGoodsAttribute> attributes = baseGoods.getGooBaseGoodsAttributeList();
        BaseGoods baseGoods1 = Repositorys.baseGoods.save(BaseGoodsFactory.initBaseFields(baseGoods));
        UUID baseGoods1UUID = baseGoods1.getUuid();
        List<GooBaseGoodsAttribute> saveAttributes = getGooBaseGoodsAttributes(attributes, baseGoods1UUID);
        baseGoods1.setGooBaseGoodsAttributeList(saveAttributes);
        //遍历保存规格
        List<GooBaseGoodsSpecification> specifications = baseGoods.getSpecifications();
        List<GooBaseGoodsSpecificationValue> values = new ArrayList<>();
        for (GooBaseGoodsSpecification specification : specifications) {
            specification.setUuid(UUIDUtils.generateUUID());
            specification.setFkGooBaseGoodsUuid(baseGoods1UUID);
            List<GooBaseGoodsSpecificationValue> specificationValues = specification.getGoodsSpecificationValues();
            GooBaseGoodsSpecification save = Repositorys.gooBaseGoodsSpecification.save(specification);
            specificationValues.forEach(item -> {
                item.setUuid(UUIDUtils.generateUUID());
                item.setUpper(save.getUuid());
            });
            values.addAll(specificationValues);
        }
        //保存规格,属性值中间表
        Repositorys.gooBaseGoodsSpecificationValue.saveAll(values);
        return baseGoods1;
    }

    @Override
    public List<BaseGoods> batchModify(List<BaseGoods> baseGoodsList) {
        //删除属性
        baseGoodsList.forEach(good -> {
            UUID uuid = good.getUuid();
            List<GooBaseGoodsAttribute> attributesDb = Repositorys.gooBaseGoodsAttribute.findAllByFkBaseGoodsUUID(uuid);
            attributesDb.forEach(item -> {
                List<GooBaseGoodsAttributeValue> attributeValues = Repositorys.gooBaseGoodsAttributeValue.findAllByUpper(item.getUuid());
                Repositorys.gooBaseGoodsAttributeValue.deleteInBatch(attributeValues);
            });
            Repositorys.gooBaseGoodsAttribute.deleteInBatch(attributesDb);

            //从数据库中查询
            GooBaseGoodsSpecification specification = new GooBaseGoodsSpecification();
            specification.setValidFlag(ValidFlag.VALID);
            specification.setFkGooBaseGoodsUuid(uuid);
            List<GooBaseGoodsSpecification> distinct = Repositorys.gooBaseGoodsSpecification.findAll(Example.of(specification));
            //删除规格,逻辑删除
            deleteSpecs(distinct);
        });



        return Repositorys.baseGoods.saveAll(baseGoodsList);
    }

    private void deleteSpecs(List<GooBaseGoodsSpecification> distinct) {
        if (!distinct.isEmpty()) {
            distinct.forEach(item -> {
                item.setValidFlag(ValidFlag.DEL);
                GooBaseGoodsSpecificationValue specificationValue = new GooBaseGoodsSpecificationValue();
                specificationValue.setValidFlag(ValidFlag.VALID);
                specificationValue.setUpper(item.getUuid());
                List<GooBaseGoodsSpecificationValue> values = Repositorys.gooBaseGoodsSpecificationValue.findAll(Example.of(specificationValue));
                values.forEach(value -> {
                    value.setValidFlag(ValidFlag.DEL);
                });
                Repositorys.gooBaseGoodsSpecificationValue.saveAll(values);
            });
            Repositorys.gooBaseGoodsSpecification.saveAll(distinct);
        }
    }
}
